package com.example.geoaimavlink_android.activity.fragment

import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
import android.text.method.ScrollingMovementMethod
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.LinearLayoutManager
import com.example.geoaimavlink_android.R
import com.example.geoaimavlink_android.activity.adapter.KeyItemAdapter
import com.example.geoaimavlink_android.activity.data.ApiMethodItem
import com.example.geoaimavlink_android.activity.data.ChannelType
import com.example.geoaimavlink_android.activity.data.IMethodInvokeBuilder
import com.example.geoaimavlink_android.activity.data.MethodInvokeBuilder
import com.example.geoaimavlink_android.activity.view.KeyValueDialogUtil
import com.example.geoaimavlink_android.utils.ApiSelectUtils
import com.google.gson.Gson
import kotlinx.android.synthetic.main.frag_func_api_invoke.et_filter
import kotlinx.android.synthetic.main.frag_func_api_invoke.recyclerView
import kotlinx.android.synthetic.main.frag_func_api_invoke.tv_count
import kotlinx.android.synthetic.main.frag_func_api_invoke.tv_operate_title
import kotlinx.android.synthetic.main.frag_func_api_invoke.tv_operate_title_lyt
import kotlinx.android.synthetic.main.layout_key_operate.bt_action
import kotlinx.android.synthetic.main.layout_key_operate.bt_get
import kotlinx.android.synthetic.main.layout_key_operate.bt_listen
import kotlinx.android.synthetic.main.layout_key_operate.bt_set
import kotlinx.android.synthetic.main.layout_key_operate.bt_unlistenall
import kotlinx.android.synthetic.main.layout_key_operate.btn_clearlog
import kotlinx.android.synthetic.main.layout_key_operate.tv_name
import kotlinx.android.synthetic.main.layout_key_operate.tv_result
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale.filter

class ApiInvokeFragment: BaseFragment() {

    private var currentChannelType: ChannelType? = ChannelType.CHANNEL_TYPE_FLIGHT_CONTROL
    private var currentIMethodInvokeBuilder: IMethodInvokeBuilder? = null
    private var currentApiMethodList: MutableList<ApiMethodItem> = mutableListOf()
    private var apiMethodAdapter: KeyItemAdapter? = null
    //存储日志文本
    private val logMessage = StringBuilder()
    //存储监听类型已经调用了的方法
    private val callbackMethodInvoked = mutableListOf<IMethodInvokeBuilder>()

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.frag_func_api_invoke, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        tv_result!!.movementMethod = ScrollingMovementMethod.getInstance()

        tv_operate_title_lyt.setOnClickListener { moduleTypeSpinnerOperate() }
        bt_action.setOnClickListener { currentIMethodInvokeBuilder?.actionInvoke { writeTextResult(it) } }
        bt_get.setOnClickListener { currentIMethodInvokeBuilder?.getInvoke { writeTextResult(it) } }
        bt_listen.setOnClickListener {
            currentIMethodInvokeBuilder?.let { builder ->
                builder.listenerInvoke(true) { writeTextResult(it) }
                callbackMethodInvoked.add(builder)
            }
        }
        bt_set.setOnClickListener {
            currentIMethodInvokeBuilder?.let {builder ->
                if (builder.getMethod().parameterTypes.size == 1) builder.setInvoke { writeTextResult(it) }
                else KeyValueDialogUtil.showApiSetParamAndInvokeWindow(bt_set, builder.getMethod()) {params ->
                    builder.setInvoke(*params) { writeTextResult(it) }
                }
            }
        }
        bt_unlistenall.setOnClickListener { callbackMethodInvoked.forEach { it.listenerInvoke(false) {  } } }
        btn_clearlog.setOnClickListener {
            tv_result?.text = ""
            logMessage.clear()
        }

        //全局映射
        ApiSelectUtils.getInstance().setInvokeCallback {
            writeTextResult("\r\n" + it)
        }
        initAdapter()
    }

    private fun initAdapter() {
        apiMethodAdapter = KeyItemAdapter(context, currentApiMethodList) {apiMethod ->
            apiMethod?.let { apiMethod ->
                currentApiMethodList.forEach { it.isSelected = false }
                apiMethod.isSelected = true
                apiMethodAdapter?.notifyDataSetChanged()
                setMethodInfo(apiMethod)
                methodSelected(currentIMethodInvokeBuilder)
            }
        }
        et_filter.addTextChangedListener(object : TextWatcher {
            override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {
                //Do Something
            }

            override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
                //Do Something
            }

            override fun afterTextChanged(s: Editable) {
                apiMethodAdapter?.filter?.filter(s.toString())
            }
        })
        recyclerView!!.layoutManager = LinearLayoutManager(activity)
        recyclerView!!.adapter = apiMethodAdapter
        processModuleApiInfo()
    }

    private fun moduleTypeSpinnerOperate() {
        KeyValueDialogUtil.showChannelFilterListWindow(tv_operate_title, ChannelType.values().toMutableList()) { channelType ->
            resetSearchFilter()
            setModuleInfo(channelType)
            processModuleApiInfo()
            resetCurrentMethodSelector()
            currentIMethodInvokeBuilder = null
        }
    }

    private fun processModuleApiInfo() {
        currentApiMethodList.clear()
        //更新接口列表
        ApiSelectUtils.getInstance().getApi(currentChannelType?.key)
            ?.filter {
                // 过滤掉removeXXXListener方法
                !it.name.contains(
                    Regex("remove[^()]*Listener")
                )
            }?.forEach {
                currentApiMethodList.add(ApiMethodItem(it.name, it))
            }
        setKeyCount(currentApiMethodList.size)
        apiMethodAdapter?.notifyDataSetChanged()
    }

    private fun setModuleInfo(currentChannelType: ChannelType?) {
        this.currentChannelType = currentChannelType
        tv_operate_title?.text = currentChannelType?.key
    }

    private fun setMethodInfo(apiMethod: ApiMethodItem) {
        this.currentIMethodInvokeBuilder = MethodInvokeBuilder(currentChannelType!!, apiMethod.method)
        tv_name?.text = apiMethod.name
    }

    private fun resetSearchFilter() {
        et_filter?.setText("")
        apiMethodAdapter?.filter?.filter("")
    }

    private fun resetCurrentMethodSelector() {
        tv_name?.text = ""
        methodSelected(null)
    }

    private fun setKeyCount(count: Int) {
        tv_count?.text = "(${count})";
    }

    private fun methodSelected(currentIMethodInvokeBuilder: IMethodInvokeBuilder?) {
        /**
         * 1. 确定找到指向这个方法
         * 2. 获取返回值、获取complete的异步获取，确认能否get
         * 3. 确认输入参数，确认是否存在complete的listener，确认是否set
         * 4. 确认是否标准的listener函数，确认是否listener
         * 5. 确认是否简单action函数
         * 6. 确认
         */
        bt_get?.isEnabled = currentIMethodInvokeBuilder?.isCanGet() ?: false
        bt_set?.isEnabled = currentIMethodInvokeBuilder?.isCanSet() ?: false
        bt_action?.isEnabled = currentIMethodInvokeBuilder?.isCanAction() ?: false
        bt_listen?.isEnabled = currentIMethodInvokeBuilder?.isCanListener() ?: false
    }

    /**
     * 写日志
     */
    private fun writeTextResult(t: Any) {
        if (t is String) {
            tv_result?.text = appendLogMessageRecord(t)
        } else {
            tv_result?.text = appendLogMessageRecord(Gson().toJson(t))
        }
        if (tv_result != null) {
            scrollToBottom()
        }
    }

    /**
     * 增加日志文件
     */
    private fun appendLogMessageRecord(appendStr: String?): String {
        val curTime = SimpleDateFormat("HH:mm:ss").format(Date())
        logMessage.append(curTime)
            .append(":")
            .append(appendStr)
            .append("\n")

        //长度限制
        var result = logMessage.toString()
        if (result.length > 6000) {
            result = result.substring(result.length - 6000)
        }
        return result
    }

    /**
     * 文本滑动到底部
     */
    private fun scrollToBottom() {
        val scrollOffset = (tv_result.layout.getLineTop(tv_result!!.lineCount)
                - tv_result!!.height)
        if (scrollOffset > 0) {
            tv_result!!.scrollTo(0, scrollOffset)
        } else {
            tv_result!!.scrollTo(0, 0)
        }
    }

    override fun onDestroyView() {
        callbackMethodInvoked.forEach { it.listenerInvoke(false) {  } }
        super.onDestroyView()
    }
}